/*
  让我们通过一个银行账户操作的例子来具体说明代理模式。
  场景背景：
  你有一个银行账户系统，其中有一个 BankAccount 类，它负责处理存款和取款等业务。
  为了增加安全性，你希望在执行存款或取款操作之前，检查用户是否有权限执行这些操作，同时记录操作日志。
  为了实现这一功能，我们可以使用代理模式，通过代理类来控制对 BankAccount 类的访问。
 */


/*
  目标类：BankAccount 是核心业务逻辑类，负责处理银行账户的存取款操作。
  代理类：BankAccountProxy 在调用 BankAccount 的方法前，先执行认证检查和日志记录，确保只有经过认证的用户才能进行操作。
  代理模式的作用：通过代理类，增强了对 BankAccount 类的访问控制，增加了安全检查和日志记录功能，而不需要修改 BankAccount 的源代码。
 */

/*
 * 代理模式的具体应用：
 * 安全控制：代理类可以在执行实际操作之前，先进行权限验证，确保只有授权用户才能执行操作。
 * 日志记录：在执行操作前后添加日志记录，方便跟踪操作历史。
 * 面向切面编程（AOP）：类似于 Spring 框架中的 AOP，可以在不修改业务逻辑的情况下，动态地添加行为。
 */

/*
    总结：
    这个银行账户操作的例子展示了静态代理模式的用法，通过代理类增强目标类的功能，如日志记录和权限验证。
    代理模式的优势在于它可以在不修改原有业务代码的情况下，增加额外的功能，从而实现更灵活、可扩展的设计。
 */

/*
静态代理的局限性
代码冗余：每个接口实现类都需要编写一个对应的代理类，容易导致代码膨胀。当接口较多时，每个接口的代理类实现逻辑大同小异，但仍然需要单独编写。
不灵活：如果系统中有很多类似的业务逻辑需要代理，静态代理的方式会显得非常不灵活，尤其是在需要对大量类进行代理时，会产生大量重复的代码。
 */
public class StaticProxy {
    public static void main(String[] args) {
        // 创建银行账户对象
        BankAccount account = new BankAccount(1000.0);

        // 创建代理对象，模拟用户已认证
        BankAccountProxy proxy = new BankAccountProxy(account, true);

        // 通过代理类操作账户
        proxy.deposit(500);    // 成功存款
        proxy.withdraw(300);   // 成功取款

        // 创建未认证的代理对象
        BankAccountProxy proxyWithoutAuth = new BankAccountProxy(account, false);

        // 未认证的用户尝试操作
        proxyWithoutAuth.deposit(200);   // 失败
        proxyWithoutAuth.withdraw(100);  // 失败
    }
}

// 银行账户类
class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // 存款方法
    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposit " + amount + ", New balance: " + balance);
    }

    // 取款方法
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println("Withdraw " + amount + ", New balance: " + balance);
        } else {
            System.out.println("Insufficient funds.");
        }
    }

    // 获取余额
    public double getBalance() {
        return balance;
    }
}

// 银行账户代理类
class BankAccountProxy {
    private BankAccount bankAccount;
    private boolean userAuthenticated;  // 模拟用户是否已认证

    public BankAccountProxy(BankAccount bankAccount, boolean userAuthenticated) {
        this.bankAccount = bankAccount;
        this.userAuthenticated = userAuthenticated;
    }

    // 代理存款方法
    public void deposit(double amount) {
        if (authenticate()) {
            System.out.println("Logging: User is depositing money.");
            bankAccount.deposit(amount);
        }
    }

    // 代理取款方法
    public void withdraw(double amount) {
        if (authenticate()) {
            System.out.println("Logging: User is withdrawing money.");
            bankAccount.withdraw(amount);
        }
    }

    // 认证方法
    private boolean authenticate() {
        if (userAuthenticated) {
            System.out.println("User authenticated.");
            return true;
        } else {
            System.out.println("User not authenticated. Access denied.");
            return false;
        }
    }
}


